﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using HP.Cachalote.Services.Shared;

namespace HP.Cachalote.WPF.Shared
{
    public enum DueDateStatus
    {
        NotStarted,     // It means this item has no due date setup or does not reach this due date yet.
        ReachDueDate,   // It means this item just reach the due date based on setup.
        ReachDueTime,   // It means this item just reach the due time based on setup.
        Overdue         // It means this item is overdue based on the due date & time as setup.
    }

    /// <summary>
    /// This class provides some methods to format the information / message for display.
    /// </summary>
    public static class InformationFormatter
    {
        /// <summary>
        /// Determine which DueDateStatus it is based on DueDate, StartTime and EndTime as setup.
        /// </summary>
        /// <param name="dueDate">The DueDate.</param>
        /// <param name="startTime">The StartTime.</param>
        /// <param name="endTime">The EndTime.</param>
        /// <returns>DueDateStatus, it includes NotStarted, ReachDueDate, ReachDueTime and Overdue.</returns>
        public static DueDateStatus GetDueDateStatus(DateTime? dueDate, DateTime? startTime, DateTime? endTime)
        {
            return GetDueDateStatus(dueDate, startTime, endTime, GeneralUtilities.GetCurrentDateTime());
        }

        /// <summary>
        /// Determine which DueDateStatus it is based on DueDate, StartTime and EndTime as setup.
        /// </summary>
        /// <param name="dueDate">The DueDate.</param>
        /// <param name="startTime">The StartTime.</param>
        /// <param name="endTime">The EndTime.</param>
        /// <param name="currentDate">The current datetime.</param>
        /// <returns>DueDateStatus, it includes NotStarted, ReachDueDate, ReachDueTime and Overdue.</returns>
        public static DueDateStatus GetDueDateStatus(DateTime? dueDate, DateTime? startTime,
            DateTime? endTime, DateTime currentDate)
        {
            // The default status.
            var status = DueDateStatus.NotStarted;

            // If the DueDate is setup and it's in the same day with the current day.
            if (dueDate.HasValue && dueDate.Value.Date == currentDate.Date)
            {
                if (!startTime.HasValue && !endTime.HasValue)
                {
                    // If the StartTime & EndTime are not setup.

                    status = DueDateStatus.ReachDueDate;
                }
                else if (startTime.HasValue && !endTime.HasValue)
                {
                    // If only the StartTime is setup.

                    if (startTime <= currentDate)
                    {
                        status = DueDateStatus.ReachDueTime;
                    }
                }
                else if (!startTime.HasValue && endTime.HasValue)
                {
                    // If only the EndTime is setup.

                    if (endTime >= currentDate)
                    {
                        status = DueDateStatus.ReachDueTime;
                    }
                    else
                    {
                        status = DueDateStatus.Overdue;
                    }
                }
                else if (startTime.HasValue && endTime.HasValue)
                {
                    // If the StartTime & EndTime are both setup.

                    if (startTime.Value <= currentDate && endTime.Value >= currentDate)
                    {
                        status = DueDateStatus.ReachDueTime;
                    }
                    else
                    {
                        status = DueDateStatus.ReachDueDate;
                    }
                }
            }
            else if (dueDate.HasValue && dueDate.Value.Date < currentDate.Date)
            {
                // If the Duedate is setup and the day is past.

                status = DueDateStatus.Overdue;
            }

            return status;
        }

        /// <summary>
        /// Show more friendly information based on DueDate.
        /// </summary>
        /// <param name="dueDate">Provided DueDate.</param>
        /// <param name="currentDate">Current date.</param>
        /// <returns>Formatted friendly DueDate information.</returns>
        public static string FormatDueDateDisplay(DateTime? dueDate, DateTime currentDate)
        {
            string formattedInfo = string.Empty;

            if (dueDate.HasValue)
            {
                if (dueDate.Value.Date < currentDate.Date)
                {
                    formattedInfo = string.Format("{0} Days", dueDate.Value.Subtract(currentDate).Days);
                }
                else if (dueDate.Value.Date == currentDate.Date)
                {
                    formattedInfo = "Today";
                }
                else if (dueDate.Value.Date == currentDate.AddDays(1).Date)
                {
                    formattedInfo = "Tomorrow";
                }
                else if (dueDate.Value.Date == currentDate.AddDays(2).Date)
                {
                    formattedInfo = "2 Days";
                }
                else if (dueDate.Value.Date == currentDate.AddDays(3).Date)
                {
                    formattedInfo = "3 Days";
                }
                else if (dueDate.Value.Date > currentDate.AddDays(3).Date &&
                    dueDate.Value.Date <= GeneralUtilities.GetDateOfSaturday(currentDate).Date)
                {
                    formattedInfo = "This Week";
                }
                else if (dueDate.Value.Date > GeneralUtilities.GetDateOfSaturday(currentDate).Date &&
                    dueDate.Value <= GeneralUtilities.GetDateOfNextSaturday(currentDate))
                {
                    formattedInfo = "Next Week";
                }
                else if (dueDate.Value > GeneralUtilities.GetDateOfNextSaturday(currentDate) &&
                    GeneralUtilities.CheckIsSameYearAndMonth(currentDate, dueDate.Value))
                {
                    formattedInfo = "This Month";
                }
                else if (GeneralUtilities.CheckIsSameYearAndNextMonth(currentDate, dueDate.Value))
                {
                    formattedInfo = "Next Month";
                }
                else if (dueDate.Value.Subtract(currentDate).Days <= 99)
                {
                    formattedInfo = string.Format("{0} {1}", dueDate.Value.Day, GeneralUtilities.GetMonthShortName(dueDate.Value.Month));
                }
                else
                {
                    formattedInfo = string.Format("{0} Days", dueDate.Value.Subtract(currentDate).Days);
                }
            }
            else
            {
                formattedInfo = "Set DueDate";
            }

            return formattedInfo;
        }

        /// <summary>
        /// Show more friendly information based on DueDate.
        /// </summary>
        /// <param name="dueDate">Provided DueDate.</param>
        /// <returns>Formatted information.</returns>
        public static string FormatDueDateDisplay(DateTime? dueDate)
        {
            return FormatDueDateDisplay(dueDate, GeneralUtilities.GetCurrentDateTime());
        }

        /// <summary>
        /// Show more friendly information based on StartTime & EndTime.
        /// </summary>
        /// <param name="dueDate">Provided DueDate.</param>
        /// <param name="startTime">Provided StartTime.</param>
        /// <param name="endTime">Provided EndTime.</param>
        /// <returns>Formatted information.</returns>
        public static string FormatDueTimeDisplay(DateTime? dueDate, DateTime? startTime, DateTime? endTime)
        {
            string dueTimeDisplay = string.Empty;
            string shortTimeFormat = "HH:mm";

            if (dueDate.HasValue)
            {
                if (startTime.HasValue && endTime.HasValue)
                {
                    dueTimeDisplay = string.Format("{0} - {1}",
                        startTime.Value.ToString(shortTimeFormat), endTime.Value.ToString(shortTimeFormat));
                }
                else if (startTime.HasValue)
                {
                    dueTimeDisplay = string.Format("Start {0}", startTime.Value.ToString(shortTimeFormat));
                }
                else if (endTime.HasValue)
                {
                    dueTimeDisplay = string.Format("End {0}", endTime.Value.ToString(shortTimeFormat));
                }
                else
                {
                    dueTimeDisplay = "All Day Event";
                }
            }
            else
            {
                dueTimeDisplay = "NA";
            }

            return dueTimeDisplay;
        }

        /// <summary>
        /// Show a error message via MessageBox.
        /// </summary>
        /// <param name="ex">The provided exception carries the error message.</param>
        public static void ShowErrorMessage(System.Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        /// <summary>
        /// Show a information message via MessageBox.
        /// </summary>
        /// <param name="ex">The content needs to be shown.</param>
        public static void ShowInformationMessage(string content)
        {
            MessageBox.Show(content, "Information", MessageBoxButton.OK, MessageBoxImage.Information);
        }
    }
}
